package awk.jndi;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.rmi.registry.LocateRegistry;
import java.util.Hashtable;
import java.util.Properties;

/**
 * @description:
 * @author: wanghaifeng
 * @date: 2021/3/1
 * 参考地址： https://blog.csdn.net/chaojixiaozhu/article/details/78931445
 * https://blog.csdn.net/guyuealian/article/details/51992182
 *
 * 在JDK 5的rt.jar中一共找到了4种SUN自带的JNDI实现：LDAP，CORBA，RMI，DNS。
 * 这4种JNDI要正常运行还需要底层的相应服务。我们没有LDAP或CORBA服务器，也就无法启动这两种JNDI服务，DNS用于查域名。唯一可以在main()中启动的就是基于RMI的JNDI服务。
 *
 */
public class Test {
    public static void main(String[] args) throws Exception {
        //这里是对象的传递，没涉及i方法的调用。方法调用时需要有接口及实现类，接口需要实现实现Remote接口，而实现类需继承UnicastRemoteObject类
        initPerson();//相当于服务端
        findPerson();//相当于客户端
    }

    /**
     *
     * @title initPerson
     * @description 绑定一个对象到JNDI服务上
     * @author hadoop
     * @throws Exception
     */
    public static void initPerson() throws Exception{
        LocateRegistry.createRegistry(3000); // 在本地主机上创建和导出注册表实例，并在指定的端口上接受请求
        //配置JNDI工厂和JNDI的url和端口。如果没有配置这些信息，将会出现NoInitialContextException异常(这里直接设置了了系统变量，也可以参见 getInitialContext() 方法)
        System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
        System.setProperty(Context.PROVIDER_URL, "rmi://localhost:3000");
        InitialContext namingContext  = new InitialContext();

        namingContext.createSubcontext("/sylilzy");

        Person person = new Person();
        person.setName("zc");
        person.setPassword("123");
        //将person对象绑定到JNDI服务中，JNDI的名字叫做：person。
        //因为已经有 System.setProperty(Context.PROVIDER_URL, "rmi://localhost:3000")设置,相当于已经设置了系统路由前缀,所以bind时不用再添加前缀，不然写法是 namingContext.rebind("rmi://localhost:8892/person", person);
        namingContext .bind("person", person);
        namingContext .close();
    }


    /**
     *
     * @title findPerson
     * @description 通过JNDI获得person对象
     * @author hadoop
     * @throws Exception
     */
    public static void findPerson() throws Exception{
        //因为前面已经将JNDI工厂和JNDI的url和端口已经添加到System对象中，这里就不用在绑定了
        InitialContext namingContext  = new InitialContext();
        //通过lookup查找person对象
        Person person = (Person) namingContext.lookup("person");
        System.out.println(person.toString());
        namingContext .close();
    }

    //从任何一个地反连接到jndi：需要先设置环境
    public Context getInitialContext() throws NamingException {
        //使用hash类链接jndi
        Hashtable env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");
        env.put(Context.PROVIDER_URL,"T3://LOCALHOST:7001");
        env.put(Context.SECURITY_PRINCIPAL,"system");
        env.put(Context.SECURITY_CREDENTIALS,"PassWord");
        Context ctx = new InitialContext(env);

        //使用Hardcoded名和Properties类
        Properties properties = new Properties();
        properties.setProperty("java.naming.factory.initial","weblogic.jndi.WLInitialContextFactory");
        properties.setProperty("java.naming.provider.url","t3:192.2.256.102:7001");
        properties.setProperty("java.naming.securiry.principal","system");
        properties.setProperty("java.naming.security.credentials","PaSsWoRd");
        ctx = new InitialContext(properties);

        //jndi.properties文件为所有的Initial Contexts设置默认属性，且文件的的搜索次序为：CLASSPATH其次是$JAVA_HOME/lib/
/*        Java.naming.factory.initial = weblogic.jndi.WLInitialContextFactory;//上下文工厂的类名。这是服务器提供者给定的类名。
        Java.naming.provider.url=t3://localhost:7001;//服务提供者所使用的配置信息。在这里指出网络位置信息，如：ip地址
        Java.naming.security.principal =system;//使用服务提供者的人员身份标识，如：用户名
        Java.naming.security.credentials =password;//该身份的密码
        */
        //没有参数，Context ctx = new InitialContext(); 相当于使用默认值


        return ctx;
    }
}
